package com.example.handler;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Author 刘武贵
 * @Date 2024-03-03 21:30
 * @Description 功能描述：处理Sentinel系统规则，返回自定义异常 （演示Sentinel的系统规则）
 */
@Component
/**
 * 自定义URL阻塞处理 handler，用于处理请求中的各种阻塞异常。
 * 实现了BlockExceptionHandler接口，用于处理泛化的阻塞异常。
 */
public class MyUrlBlockHandler implements BlockExceptionHandler {

    /**
     * 处理请求中的阻塞异常。
     * 根据不同的异常类型，返回不同的错误信息。
     *
     * @param request  HttpServletRequest对象，代表客户端的HTTP请求
     * @param response HttpServletResponse对象，用于向客户端发送响应
     * @param e        阻塞异常对象，具体类型依赖于具体的阻塞场景
     * @throws Exception 抛出异常，用于处理无法正常处理的情况
     */
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        String msg = null;
        // 根据不同的异常类型，设置不同的错误信息
        if (e instanceof FlowException) {
            msg = "限流了";
        } else if (e instanceof DegradeException) {
            msg = "降级了";
        } else if (e instanceof ParamFlowException) {
            msg = "热点参数限流";
        } else if (e instanceof SystemBlockException) {
            msg = "系统规则（负载/...不满足要求）";
        } else if (e instanceof AuthorityException) {
            msg = "授权规则不通过";
        }

        // 设置HTTP响应状态码为500，表示服务器内部错误
        response.setStatus(500);
        // 设置响应的字符编码和内容类型
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        response.setContentType("application/json;charset=utf-8");

        // 构建JSON对象，包含错误代码和错误信息
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", 500);
        jsonObject.put("codeMsg", msg);

        // 将JSON对象转换为字符串，并写入响应体中
        response.getWriter().write(jsonObject.toJSONString());
    }
}
